import React, { Component } from 'react'
import { message } from 'antd'
import netmap from './index.module.css'

import camera_icon from '../../asserts/images/camera_icon.png' 
import submit_icon from '../../asserts/images/submit_icon.png'
import avatar_mask from '../../asserts/images/avatar_mask.png'

import {uploadPicture} from '../../api/monitor'

export default class CameraCapture extends Component {

  constructor(props){
    super(props);
    this.state = {
      stream: null,
      type: 'contain',
      imgSrc: null,

      videoWidth: 0,
      videoHeight: 0,
    };
    this.videoRef = React.createRef()
    this.videoWrapRef = React.createRef()
    this.canvasRef = React.createRef()
  }

  componentDidMount(){

    // 老的浏览器可能根本没有实现 mediaDevices，所以我们可以先设置一个空的对象
    if (navigator.mediaDevices === undefined) {
      navigator.mediaDevices = {};
    }

    // 一些浏览器部分支持 mediaDevices。我们不能直接给对象设置 getUserMedia
    // 因为这样可能会覆盖已有的属性。这里我们只会在没有 getUserMedia 属性的时候添加它。
    if (navigator.mediaDevices.getUserMedia === undefined) {
      navigator.mediaDevices.getUserMedia = function (constraints) {
        // 首先，如果有 getUserMedia 的话，就获得它
        var getUserMedia =
          navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

        // 一些浏览器根本没实现它 - 那么就返回一个 error 到 promise 的 reject 来保持一个统一的接口
        if (!getUserMedia) {
          return Promise.reject(
            new Error("getUserMedia is not implemented in this browser"),
          );
        }

        // 否则，为老的 navigator.getUserMedia 方法包裹一个 Promise
        return new Promise(function (resolve, reject) {
          getUserMedia.call(navigator, constraints, resolve, reject);
        });
      };
    }



    if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
      // 浏览器不支持 getUserMedia，可能需要引入 Polyfill 或提示用户
      console.log('当前浏览器不支持 getUserMedia API')
    } else {
      // 浏览器支持 getUserMedia，可以正常使用拍照功能
      // 调用相关函数来初始化摄像头等操作
      // 访问用户摄像头设备
      this.initCamera()
    }
  }

  componentDidUpdate(){
  }
  componentWillUnmount(){
    this.closeCamera()
  }

  initCamera = async () => {
    let videoWidth = 640, videoHeight = 480
    if (this.videoWrapRef.current) {
      videoWidth = this.videoWrapRef.current.clientWidth
      videoHeight = this.videoWrapRef.current.clientHeight
    }

    var proportion = videoHeight / videoWidth
    let type = 'contain'
    if(proportion  > 1.3){
      type='cover' //cover	保持原有尺寸比例。但部分内容可能被剪切。
    }else{
      type='contain' //contain	保持原有尺寸比例。内容被缩放
    }
    this.setState({
      type,
      videoWidth,
      videoHeight
    })
    
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ video: { width: videoWidth, height: videoHeight } });
      this.setState({ stream });

      if (this.videoRef.current) {
        // 旧的浏览器可能没有 srcObject
        if ("srcObject" in this.videoRef.current) {
          this.videoRef.current.srcObject = stream;
        } else {
          // 防止在新的浏览器里使用它，应为它已经不再支持了
          this.videoRef.current.src = window.URL.createObjectURL(stream);
        }
        this.videoRef.current.onloadedmetadata =  (e) => {
          this.videoRef.current.play();
        };
      }

    } catch (error) {
      console.error('Error accessing camera: ', error);
      if (error == 'NotFoundError: Requested device not found') {
        message.warning('没有找到摄像头！')
      }
    }
  }

  closeCamera = () => {
    // 关闭摄像头流
    const { stream } = this.state;
    if (stream) {
      stream.getTracks().forEach(track => track.stop());
    }
  }

  takePicture = () => {
    if (!this.state.stream) return

    const video = this.videoRef.current;
    const canvas = this.canvasRef.current;
    console.log(video.videoWidth, video.videoHeight);
    
    if (video && canvas) {
      canvas.width = video.videoWidth;
      canvas.height = video.videoHeight;
      const ctx = canvas.getContext('2d');
      ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
      const imageData = canvas.toDataURL('image/jpeg', 1.0);
      // console.log('Captured Image: ', imageData);
      this.setState({imgSrc: imageData},() => {this.closeCamera()});
    }
  }

  clearPicture = () => {
    this.setState({imgSrc: null}, () => {
      this.initCamera()
      this.props.onClearPicture()
    });
  }

  submitPicture = () => {
    if (!this.state.imgSrc) {
      message.warning('请先拍照！')
      return
    }


    this.props.onSubmitLoading(true)

    const file = this.base64ToFile(this.state.imgSrc, 'facial.jpeg');
    const formData = new FormData()
    formData.append('file', file)


    // 注意：通常不需要设置{'Content-Type': 'multipart/form-data'},因为axios会自动处理'multipart/form-data'
    uploadPicture(formData).then(uploadRes => {
      console.log(uploadRes)
      if (uploadRes.code === 200) {
        const result = uploadRes.data
        this.props.onSubmitPicture({result})
      }else if (uploadRes.code === 500) {
        message.error('未检测到人脸！')
      }
      this.props.onSubmitLoading(false)
    }).catch(uploadErr => {
      console.log(uploadErr)
      this.props.onSubmitLoading(false)
    })
  }

  // 将 Base64 图片数据转换为 File 对象
  base64ToFile = (base64Data, fileName, mimeType) => {
    // 拆分Base64字符串
    const parts = base64Data.split(';base64,');
    const contentType = mimeType || parts[0].split(':')[1];
    const raw = window.atob(parts[1]);
    const rawLength = raw.length;
    const uInt8Array = new Uint8Array(rawLength);

    for (var i = 0; i < rawLength; i++) {
      uInt8Array[i] = raw.charCodeAt(i);
    }

    // 创建Blob对象
    const blob = new Blob([uInt8Array], { type: contentType });

    // 创建File对象（在浏览器环境中模拟文件）
    return new File([blob], fileName, { type: contentType });
  }

  render() {
    return (
      <div className={netmap.container}>
        <div className={netmap.video_outer_wrap}>
          {
            !this.state.stream && (
              <div className={netmap.not_found}>没有找到摄像头！</div>
            )
          }
          {
            this.state.imgSrc && (
              <div className={netmap.captured_img_wrap}>
                <img src={this.state.imgSrc} alt="" />
              </div>
            )
          }
          <div className={netmap.video_wrap} ref={this.videoWrapRef}>
            <video ref={this.videoRef} 
              autoPlay 
              playsInline 
              style={{width: '100%',height: '100%', objectFit: this.state.type}}
            ></video>
          </div>
          {
            !this.state.imgSrc && 
            // <div className={netmap.mask} style={{width: this.state.videoWidth, height: this.state.videoHeight}}>
            <div className={netmap.mask}>
              <img src={avatar_mask} alt="" />
            </div>
          }
          {
            !this.state.imgSrc && 
            <div className={netmap.tips}>请将人脸放置在取景框中</div>
          }
        </div>
        <div className={netmap.btns}>
          {
            this.state.imgSrc ?
              <button className={netmap.btn} onClick={this.clearPicture}>
                <img src={camera_icon} alt="" />
                重拍
              </button>
            :
              <button className={netmap.btn} onClick={this.takePicture}>
                <img src={camera_icon} alt="" />
                拍照
              </button>
          }
          <button className={netmap.btn} onClick={this.submitPicture}>
            <img src={submit_icon} alt="" />
            提交
          </button>
        </div>
        <canvas ref={this.canvasRef} style={{ display: 'none' }}></canvas>
      </div>
    )
  }
}
